/**
 * 
 */
package co.fitstart.coach.dao;

import java.util.Date;
import java.util.List;

import com.demo2do.core.persistence.annotation.Dynamic;
import com.demo2do.core.persistence.annotation.Limit;
import com.demo2do.core.persistence.annotation.Query;
import com.demo2do.core.persistence.annotation.Variable;

import co.fitstart.entity.coach.CoachRestCalendar;
import co.fitstart.entity.coach.CoachRestType;
import co.fitstart.entity.course.CourseType;
import co.fitstart.entity.course.round.CourseRound;
import co.fitstart.entity.course.round.RoundStatus;
import co.fitstart.entity.course.schedule.CourseSchedule;
import co.fitstart.entity.course.schedule.ScheduleStatus;
import co.fitstart.entity.principal.Principal;
import co.fitstart.entity.user.Student;

/**
 * @author downpour
 *
 */
@Dynamic("hibernate")
public interface CourseDao {

    /**
     * list CourseSchedule
     * 
     * @param coach
     * @param occurDate
     * @param occurHour
     * @return
     */
    @Query("FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.coach = :coach AND courseSchedule.occurDate = :occurDate AND courseSchedule.occurHour = :occurHour")
    public List<CourseSchedule> listCourseSchedule(@Variable("coach")Principal coach, @Variable("occurDate")Date occurDate, @Variable("occurHour")String occurHour);
    
    /**
     * 
     * @param courseRound
     * @param occurDate
     * @param occurHour
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND courseRound = :courseRound AND occurDate <= :occurDate AND occurHour < :occurHour AND scheduleStatus = 2 ORDER BY occurDate DESC, occurHour DESC")
    public List<CourseSchedule> listCourseSchedule(@Variable("courseRound") CourseRound courseRound, @Variable("occurDate") Date occurDate, @Variable("occurHour") String occurHour);
    
    /**
     * list weekly courseSchedule
     * 
     * @param coach
     * @param startDate
     * @param endDate
     * @param status
     * @return
     */
    @Query("FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.coach = :coach AND courseSchedule.occurDate >= :startDate AND courseSchedule.occurDate <= :endDate AND courseSchedule.scheduleStatus in ( :status ) ORDER BY occurHour")
    public List<CourseSchedule> listWeeklyCourseSchedule(@Variable("coach")Principal coach, @Variable("startDate")Date startDate, @Variable("endDate")Date endDate, @Variable("status")List<ScheduleStatus> status);
    
    /**
     * 
     * @param courseRound
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND courseRound = :courseRound AND occurDate IS NOT NULL ORDER BY occurDate DESC")
    public List<CourseSchedule> listCourseSchedule(@Variable("courseRound") CourseRound courseRound);
    
    /**
     * list courseRound by student and courseType
     * 
     * @param student
     * @param courseType
     * @return
     */
    @Query("FROM CourseRound courseRound WHERE courseRound.disabled = false AND courseRound.courseType = :courseType AND courseRound.student = :student")
    public List<CourseRound> listCourseRound(@Variable("student")Student student, @Variable("courseType")CourseType courseType);
    
    /**
     * 
     * @param student
     * @param courseType
     * @param courseStatus
     * @return
     */
    @Query("FROM CourseRound courseRound WHERE courseRound.disabled = false AND courseRound.courseType = :courseType AND courseRound.student = :student AND courseRound.courseStatus = :courseStatus ORDER BY createTime DESC")
    public List<CourseRound> listCourseRound(@Variable("student")Student student, @Variable("courseType")CourseType courseType, @Variable("courseStatus") RoundStatus courseStatus);
    
    /**
     * 
     * @param student
     * @param courseType
     * @param courseStatus
     * @return
     */
    @Query("FROM CourseRound courseRound WHERE courseRound.disabled = false AND courseRound.courseType = :courseType AND courseRound.student = :student AND courseRound.courseStatus IN (:courseStatus) ORDER BY courseStatus ASC,createTime DESC")
    public List<CourseRound> listCourseRound(@Variable("student")Student student, @Variable("courseType")CourseType courseType, @Variable("courseStatus") List<RoundStatus> courseStatus);
    
    /**
     * count FinishedSchedule
     * 
     * @param courseRound
     * @param scheduleStatus
     * @return
     */
    @Query("SELECT COUNT(*) FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.courseRound = :courseRound AND courseSchedule.scheduleStatus = :scheduleStatus")
    public int countFinishedSchedule(@Variable("courseRound")CourseRound courseRound, @Variable("scheduleStatus")ScheduleStatus scheduleStatus);
    
    
    /**
     * count all schedule
     * 
     * @param courseRound
     * @return
     */
    @Query("SELECT COUNT(*) FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.courseRound = :courseRound")
    public int countAllSchedule(@Variable("courseRound")CourseRound courseRound);
    
    
    /**
     * load CoachRestCalendar 
     * 
     * @param coach
     * @param restDate
     * @param restHour
     * @return
     */
    @Query("FROM CoachRestCalendar coachRestCalendar WHERE coachRestCalendar.disabled = false AND coachRestCalendar.coach = :coach AND coachRestCalendar.restDate = :restDate AND coachRestCalendar.restHour = :restHour")
    public CoachRestCalendar loadCoachRestCalendar(@Variable("coach")Principal coach, @Variable("restDate")Date restDate, @Variable("restHour")String restHour);
    
    
    /**
     * list Weekly CoachRestCalendar 
     * 
     * @param coach
     * @param startDate
     * @param endDate
     * @return
     */
    @Query("FROM CoachRestCalendar coachRestCalendar WHERE coachRestCalendar.disabled = false AND coachRestCalendar.coach = :coach AND coachRestCalendar.restDate >= :startDate AND coachRestCalendar.restDate <= :endDate ORDER BY restHour")
    public List<CoachRestCalendar> listWeeklyCoachRestCalendar(@Variable("coach")Principal coach, @Variable("startDate")Date startDate, @Variable("endDate")Date endDate);
    
    /**
     * 
     * @param coach
     * @param startDate
     * @param endDate
     * @param coachRestType
     * @return
     */
    @Query("FROM CoachRestCalendar coachRestCalendar WHERE coachRestCalendar.disabled = false AND coachRestCalendar.coach = :coach AND coachRestCalendar.restDate >= :startDate AND coachRestCalendar.restDate <= :endDate AND coachRestCalendar.coachRestType = :coachRestType ORDER BY restHour")
    public List<CoachRestCalendar> listWeeklyRestCalendar(@Variable("coach")Principal coach, @Variable("startDate")Date startDate, @Variable("endDate")Date endDate, @Variable("coachRestType")CoachRestType coachRestType);
    
    /**
     * 
     * @param coach
     * @param day
     * @return
     */
    @Query("SELECT coachRestCalendar.restHour FROM CoachRestCalendar coachRestCalendar WHERE coachRestCalendar.disabled = false AND coachRestCalendar.coach = :coach AND coachRestCalendar.restDate = :day AND coachRestCalendar.coachRestType = :type ORDER BY restHour")
    public List<String> listDailyCoachRestCalendar(@Variable("coach")Principal coach, @Variable("day") Date day, @Variable("type") CoachRestType type);
    
    /**
     * 
     * @param coach
     * @param date
     * @return
     */
    @Query("SELECT courseSchedule.occurHour FROM CourseSchedule courseSchedule WHERE courseSchedule.disabled = false AND courseSchedule.coach = :coach AND courseSchedule.occurDate = :date")
    public List<String> listCourseHours(@Variable("coach") Principal coach, @Variable("date") Date date);
    
    /**
     * 
     * @param coach
     * @param restDate
     * @return
     */
    @Query("SELECT calendar.restHour FROM CoachRestCalendar calendar WHERE calendar.disabled = false AND calendar.coach = :coach AND calendar.restDate = :restDate")
    public List<String> listCoachRestHour(@Variable("coach") Principal coach, @Variable("restDate") Date restDate);
    
    /**
     * 
     * 
     * @param coach
     * @param restDate
     * @param coachRestType
     * @return
     */
    @Query("SELECT calendar.restHour FROM CoachRestCalendar calendar WHERE calendar.disabled = false AND calendar.coach = :coach AND calendar.restDate = :restDate AND coachRestType in(:types)")
    public List<String> listCoachRestHour(@Variable("coach") Principal coach, @Variable("restDate") Date restDate, @Variable("types") CoachRestType ... types);
    
    /**
     * 
     * @param coach
     * @param day
     * @param hour
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND coach = :coach AND occurDate = :day AND occurHour in (:hours)")
    public List<CourseSchedule> loadCourseSchedule(@Variable("coach") Principal coach, @Variable("day") Date day, @Variable("hours") List<String> hours);
    
    /**
     * 
     * @param courseRound
     * @param scheduleStatus
     * @param beginIndex
     * @param maxResult
     * @return
     */
    @Limit
    @Query("FROM CourseSchedule WHERE disabled = false AND courseRound = :courseRound AND scheduleStatus in ( :scheduleStatus) ORDER BY occurDate DESC")
    public List<CourseSchedule> listCourseSchedule(@Variable("courseRound") CourseRound courseRound, @Variable("scheduleStatus") List<ScheduleStatus> scheduleStatus, @Variable("beginIndex") int beginIndex, @Variable("maxResult") int maxResult);
    
    /**
     * 
     * @param courseRound
     * @param scheduleStatus
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND courseRound = :courseRound AND scheduleStatus in ( :scheduleStatus) ORDER BY occurDate ASC,occurHour ASC")
    public List<CourseSchedule> listCourseSchedule(@Variable("courseRound") CourseRound courseRound, @Variable("scheduleStatus") ScheduleStatus[] scheduleStatus);

    /**
     * 
     * @param coach
     * @param scheduleStatus
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND coach = :coach AND scheduleStatus = :scheduleStatus AND grade IS NULL ORDER BY occurDate DESC, occurHour DESC")
    public List<CourseSchedule> listUngradedSchedule(@Variable("coach") Principal coach, @Variable("scheduleStatus") ScheduleStatus scheduleStatus);

    /**
     * 
     * @param coach
     * @param scheduleStatus
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND coach = :coach AND scheduleStatus = :scheduleStatus AND grade IS NOT NULL ORDER BY occurDate DESC, occurHour DESC")
    public List<CourseSchedule> listGradedSchedule(@Variable("coach") Principal coach, @Variable("scheduleStatus") ScheduleStatus scheduleStatus);

    /**
     * 
     * @param courseRound
     * @param scheduleStatus
     * @return
     */
    @Query("FROM CourseSchedule WHERE disabled = false AND courseRound = :courseRound AND scheduleStatus = :scheduleStatus ORDER BY occurDate ASC, occurHour ASC")
    public List<CourseSchedule> listCourseSchedule(@Variable("courseRound") CourseRound courseRound, @Variable("scheduleStatus") ScheduleStatus scheduleStatus);
}
